]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
status/keyboard: Add support for IBus input sources
authorRui Matos <tiagomatos@gmail.com>
Tue, 29 May 2012 17:30:14 +0000 (19:30 +0200)
committerRui Matos <tiagomatos@gmail.com>
Sun, 15 Jul 2012 22:59:11 +0000 (00:59 +0200)
We connect to the IBus daemon asyncronously and use it to query info
about input sources of the type 'ibus'. In case the daemon is or
becomes unreachable we just skip showing input sources of this type.

https://bugzilla.gnome.org/show_bug.cgi?id=641531

js/ui/status/keyboard.js

index db02a36ec8e3e94fd9ff6d66f3c2657924c491c8..e9edef4f1f8f191a8cc78fba6fcc4655c3e41cb5 100644 (file)
@@ -6,9 +6,19 @@ const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GnomeDesktop = imports.gi.GnomeDesktop;
 const Lang = imports.lang;
+const Mainloop = imports.mainloop;
 const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 
+try {
+    var IBus = imports.gi.IBus;
+    if (!('new_async' in IBus.Bus))
+        throw "IBus version is too old";
+} catch (e) {
+    var IBus = null;
+    log(e);
+}
+
 const Main = imports.ui.main;
 const PopupMenu = imports.ui.popupMenu;
 const PanelMenu = imports.ui.panelMenu;
@@ -19,6 +29,70 @@ const KEY_CURRENT_INPUT_SOURCE = 'current';
 const KEY_INPUT_SOURCES = 'sources';
 
 const INPUT_SOURCE_TYPE_XKB = 'xkb';
+const INPUT_SOURCE_TYPE_IBUS = 'ibus';
+
+const IBusManager = new Lang.Class({
+    Name: 'IBusManager',
+
+    _init: function(readyCallback) {
+        if (!IBus)
+            return;
+
+        IBus.init();
+
+        this._readyCallback = readyCallback;
+
+        this._ibus = null;
+        this._engines = {};
+        this._ready = false;
+
+        this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS,
+                                                          Gio.BusNameWatcherFlags.NONE,
+                                                          Lang.bind(this, this._onNameAppeared),
+                                                          Lang.bind(this, this._clear));
+    },
+
+    _clear: function() {
+        if (this._ibus)
+            this._ibus.destroy();
+
+        this._ibus = null;
+        this._engines = {};
+        this._ready = false;
+    },
+
+    _onNameAppeared: function() {
+        this._ibus = IBus.Bus.new_async();
+        this._ibus.connect('connected', Lang.bind(this, this._onConnected));
+    },
+
+    _onConnected: function() {
+        this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
+        this._ibus.connect('disconnected', Lang.bind(this, this._clear));
+    },
+
+    _initEngines: function(ibus, result) {
+        let enginesList = this._ibus.list_engines_async_finish(result);
+        if (enginesList) {
+            for (let i = 0; i < enginesList.length; ++i) {
+                let name = enginesList[i].get_name();
+                this._engines[name] = enginesList[i];
+            }
+            this._ready = true;
+            if (this._readyCallback)
+                this._readyCallback();
+        } else {
+            this._clear();
+        }
+    },
+
+    getEngineDesc: function(id) {
+        if (!IBus || !this._ready)
+            return null;
+
+        return this._engines[id];
+    }
+});
 
 const LayoutMenuItem = new Lang.Class({
     Name: 'LayoutMenuItem',
@@ -58,6 +132,8 @@ const InputSourceIndicator = new Lang.Class({
         this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
         this._xkbInfo = new GnomeDesktop.XkbInfo();
 
+        this._ibusManager = new IBusManager(Lang.bind(this, this._inputSourcesChanged));
+
         this._inputSourcesChanged();
 
         // re-using "allowSettings" for the keyboard layout is a bit shady,
@@ -120,13 +196,20 @@ const InputSourceIndicator = new Lang.Class({
         let infosByShortName = {};
 
         for (let i = 0; i < nSources; i++) {
+            let info = { exists: false };
             let [type, id] = sources.get_child_value(i).deep_unpack();
-            if (type != INPUT_SOURCE_TYPE_XKB)
-                continue;
 
-            let info = {};
-            [info.exists, info.displayName, info.shortName, , ] =
-                this._xkbInfo.get_layout_info(id);
+            if (type == INPUT_SOURCE_TYPE_XKB) {
+                [info.exists, info.displayName, info.shortName, , ] =
+                    this._xkbInfo.get_layout_info(id);
+            } else if (type == INPUT_SOURCE_TYPE_IBUS) {
+                let engineDesc = this._ibusManager.getEngineDesc(id);
+                if (engineDesc) {
+                    info.exists = true;
+                    info.displayName = engineDesc.get_longname();
+                    info.shortName = engineDesc.get_symbol();
+                }
+            }
 
             if (!info.exists)
                 continue;
@@ -175,8 +258,19 @@ const InputSourceIndicator = new Lang.Class({
 
         let sources = this._settings.get_value(KEY_INPUT_SOURCES);
         let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
-        let id = sources.get_child_value(current).deep_unpack()[1];
-        let [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
+        let [type, id] = sources.get_child_value(current).deep_unpack();
+        let xkbLayout = '';
+        let xkbVariant = '';
+
+        if (type == INPUT_SOURCE_TYPE_XKB) {
+            [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
+        } else if (type == INPUT_SOURCE_TYPE_IBUS) {
+            let engineDesc = this._ibusManager.getEngineDesc(id);
+            if (engineDesc) {
+                xkbLayout = engineDesc.get_layout();
+                xkbVariant = '';
+            }
+        }
 
         if (!xkbLayout || xkbLayout.length == 0)
             return;